<?php
if (!defined('__COLA_DIR__')) exit;
/**
 * 分类输出组件
 *
 * @author edikud
 * @package Widget
 * @copyright Copyright (c) 2019 Cola (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */

class Widget_Metas_Category_List extends Widget_Abstract_Metas
{
    /**
     * _categoryOptions
     * 
     * @var mixed
     * @access private
     */
    private $_categoryOptions = NULL;

    /**
     * 所有分类哈希表 
     * 
     * @var array
     * @access private
     */
    private $_map = array();

    protected static $categories = NULL;
	
    /**
     * 构造函数,初始化组件
     *
     * @access public
     * @param mixed $request request对象
     * @param mixed $response response对象
     * @param mixed $params 参数列表
     */
    public function __construct($request, $response, $params = NULL)
    {
        parent::__construct($request, $response, $params);
		
		// ignore 忽略某个分类(注意：包括子分类)
        $this->parameter->setDefault('ignore=0');

	    NULL === self::$categories && self::$categories = $this->select()
		    ->where('type = ?', 'category')
			->order('table.metas.order', 'ASC')
			->fetchAll();

	    $this->_map = Common::buildTree(self::$categories, 'mid', 'parent');

        if ($this->parameter->ignore) {
			$ignore = explode(',', $this->parameter->ignore);
			$list = array();
            foreach ($ignore as $mid) {
                if (isset($this->_map[$mid])) {
					$list += $this->getAllChildren($mid);
                }
            }
			if ($list) {
                foreach ($list as $val) {
					unset($this->_map[$val['mid']]);
                }
				$this->_map = Common::buildTree(array_values($this->_map), 'mid', 'parent');
			}
        }
        $this->_map = array_map(array($this, 'filter'), $this->_map);
    }
	
    # 获取某个分类所有直系父级节点mid (包括自己)
    public function getParentsMids($mid)
    {
        $categorylist = $this->_map;
        $result = [];
        if (!isset($categorylist[$mid])) {
            return $result;
        }
        $parent = $mid;
        while ($parent) {
            $result[] = $parent;
            $parent = $categorylist[$parent]['parent'];
        }
        $result && ($result = array_reverse($result));

        return $result;
    }
    /**
     * 获取某个分类所有直系父级节点缩略名 (包括自己)
     * 
     * @param mixed $mid 
     * @access public
     * @return array
     */
    public function getParentsAlias($mid)
    {
        $categorylist = $this->_map;
        $result = [];
        if (!isset($categorylist[$mid])) {
            return $result;
        }
        $parent = $mid;
        while ($parent) {
            $result[] = $this->_map[$parent]['alias'];
            $parent = $categorylist[$parent]['parent'];
        }
        $result && ($result = array_reverse($result));

        return $result;
    }
    /**
     * 获取某个分类所有直系父级节点 (包括自己)
     * 
     * @param mixed $mid 
     * @access public
     * @return array
     */
    public function getParents($mid)
    {
        $categorylist = $this->_map;
        $result = [];
        if (!isset($categorylist[$mid])) {
            return $result;
        }
        $parent = $mid;
        while ($parent) {
            $result[$parent] = $this->_map[$parent];
            $parent = $categorylist[$parent]['parent'];
        }
        $result && ($result = array_reverse($result));

        return $result;
    }
	
	
    /**
     * 获取某个分类所有父级节点
     * 
     * @param mixed $mid 
     * @access public
     * @return array
     */
    public function getAllParents($mid)
    {
		$result = [];
		if (!$mid) return $result;
        $category_direct = $this->getParentsMids($mid);
		if (!$category_direct) return $result;
        $level = count($category_direct) - 1;
        $parent = $category_direct[0];
        if ($level == 1) {
            $categorylist = $this->_map;
            return $categorylist[$parent];
        }
        $list = $this->getAllChildren($parent);
        
        foreach ($list as $category) {
            if ($category['level'] < $level) {
                $result[$category['mid']] = $category;
            }
        }
        return $result;
    }
	
	
    /**
     * 获取某个分类下的所有子节点(包括自己)
     * 
     * @param mixed $mid 
     * @access public
     * @return array
     */
    public function getAllChildren($mid)
    {
        $categorylist = $this->_map;
        $result = [];

        if (!isset($categorylist[$mid])) {
            return $result;
        }
        $result = array_slice($categorylist, $categorylist[$mid]['offset'], $categorylist[$mid]['num'], true);
		
        return $result;
    }

    /**
     * 获取单个分类
     * 
     * @param integer $mid 
     * @access public
     * @return mixed
     */
    public function getCategory($mid)
    {
        return isset($this->_map[$mid]) ? $this->_map[$mid] : NULL;
    }

    /**
     * 获取多个分类 
     * 
     * @param mixed $mids 
     * @access public
     * @return array
     */
    public function getCategories()
    {
        return $this->_map;
    }

    /**
     * 执行函数
     *
     * @access public
     * @return void
     */
    public function execute()
    {
        $this->stack = $this->_map;
    }


    /**
     * 根据深度余数输出
     *
     * @access public
     * @return void
     */
    public function levelAlt()
    {
        $args = func_get_args();
        $num = func_num_args();
        $split = $this->level % $num;
        echo $args[(0 == $split ? $num : $split) -1];
    }
	
    /**
     * 将每行的值压入堆栈
     *
     * @access public
     * @param array $value 每行的值
     * @return array
     */
    public function filter(array $value)
    {
		if (isset($value['mid'])) {	
            $value['directory'] = $this->getParentsAlias($value['mid']);

            $tmpCategoryTree = $value['directory'];
            $value['directory'] = implode('/', array_map('urlencode', $value['directory']));

            $value = parent::filter($value);
            $value['directory'] = $tmpCategoryTree;
		}

        return $value;
    }
}

